# -*- coding:utf-8 -*-
# @FileName : app\api\v1\conversations\schemas.py
# @Time     : 2025/11/28
# @Author   : 天空之城
"""对话模块数据模式文件

此模块使用Marshmallow定义对话和消息数据的验证和序列化模式。
支持与agent_service.py的交互，包括工具调用记录、执行状态追踪等功能。
"""
from marshmallow import Schema, fields, validate, validates, ValidationError
from datetime import datetime
from typing import Dict, Any, List, Optional


class AgentToolCallSchema(Schema):
    """Agent工具调用记录模式
    
    用于验证和序列化Agent工具调用的记录。
    """
    id = fields.Str(required=True)  # 工具调用ID
    name = fields.Str(required=True)  # 工具名称
    arguments = fields.Dict(required=True)  # 工具调用参数
    status = fields.Str(validate=validate.OneOf(['pending', 'processing', 'completed', 'failed']), 
                       default='pending')  # 调用状态
    result = fields.Raw(allow_none=True)  # 工具调用结果
    error = fields.Str(allow_none=True)  # 错误信息
    created_at = fields.DateTime(dump_only=True)  # 创建时间
    completed_at = fields.DateTime(allow_none=True)  # 完成时间
    execution_time = fields.Float(allow_none=True)  # 执行时间（秒）


class AgentMessageMetadataSchema(Schema):
    """Agent消息元数据模式
    
    用于验证和序列化Agent消息的元数据信息。
    """
    model = fields.Str(allow_none=True)  # 使用的模型名称
    prompt_tokens = fields.Int(allow_none=True)  # Prompt token数量
    completion_tokens = fields.Int(allow_none=True)  # Completion token数量
    total_tokens = fields.Int(allow_none=True)  # 总token数量
    processing_time = fields.Float(allow_none=True)  # 处理时间（秒）
    temperature = fields.Float(allow_none=True)  # 模型温度参数
    max_tokens = fields.Int(allow_none=True)  # 最大token数量
    finish_reason = fields.Str(allow_none=True)  # 完成原因
    agent_iterations = fields.Int(allow_none=True)  # Agent迭代次数
    tool_calls_count = fields.Int(allow_none=True)  # 工具调用次数
    error_message = fields.Str(allow_none=True)  # 错误信息
    execution_context = fields.Dict(allow_none=True)  # 执行上下文
    screenshot_info = fields.Dict(allow_none=True)  # 截图相关信息


class ConversationSchema(Schema):
    """对话数据模式
    
    用于验证和序列化对话数据，定义了对话数据的结构和验证规则。
    支持与Agent服务交互的各种功能。
    """
    id = fields.Int(dump_only=True)  # 对话ID
    user_id = fields.Int(dump_only=True)  # 所属用户ID
    title = fields.Str(required=True, validate=validate.Length(min=1, max=100))  # 对话标题
    mode = fields.Str(validate=validate.OneOf(['chat', 'task_runner']), default='chat')  # 对话模式
    status = fields.Str(validate=validate.OneOf(['进行中', '已完成', '失败']), default='进行中')  # 对话状态
    execution_id = fields.Str(allow_none=True)  # 任务执行ID（用于MCP任务追踪）
    meta_data = fields.Dict(allow_none=True)  # 元数据（执行上下文、工具调用统计等）
    model_name = fields.Str(allow_none=True)  # 使用的模型名称
    created_at = fields.DateTime(dump_only=True)  # 创建时间
    updated_at = fields.DateTime(dump_only=True)  # 更新时间
    
    # 验证器
    @validates('title')
    def validate_title(self, value):
        """验证对话标题"""
        if not value or not value.strip():
            raise ValidationError('对话标题不能为空')
        
        if len(value.strip()) < 1:
            raise ValidationError('对话标题长度不能少于1个字符')
            
        if len(value) > 100:
            raise ValidationError('对话标题长度不能超过100个字符')
    
    class Meta:
        """元数据
        
        指定JSON序列化的额外配置。
        """
        ordered = True


class MessageSchema(Schema):
    """消息数据模式
    
    用于验证和序列化消息数据，定义了消息数据的结构和验证规则。
    支持与Agent服务交互，包括工具调用记录、执行状态追踪等功能。
    """
    id = fields.Int(dump_only=True)  # 消息ID
    conversation_id = fields.Int(dump_only=True)  # 所属对话ID
    role = fields.Str(required=True, validate=validate.OneOf(['user', 'assistant', 'system', 'tool']))  # 角色
    content = fields.Str(required=True, validate=validate.Length(min=1))  # 消息内容
    image_path = fields.Str(allow_none=True)  # 截图文件路径
    tool_calls = fields.List(fields.Nested(AgentToolCallSchema), allow_none=True)  # 工具调用记录列表
    tool_results = fields.Dict(allow_none=True)  # 工具调用结果字典
    status = fields.Str(validate=validate.OneOf(['pending', 'processing', 'completed', 'failed']), 
                       default='pending')  # 消息状态
    meta_data = fields.Nested(AgentMessageMetadataSchema, allow_none=True)  # 消息元数据
    created_at = fields.DateTime(dump_only=True)  # 创建时间
    
    # 验证器
    @validates('role')
    def validate_role(self, value):
        """验证消息角色"""
        valid_roles = ['user', 'assistant', 'system', 'tool']
        if value not in valid_roles:
            raise ValidationError(f'角色必须是以下之一: {", ".join(valid_roles)}')
    
    @validates('content')
    def validate_content(self, value):
        """验证消息内容"""
        if not value or not value.strip():
            raise ValidationError('消息内容不能为空')
        
        if len(value.strip()) > 8000:  # 设置消息长度限制
            raise ValidationError('消息内容不能超过8000个字符')
    
    class Meta:
        """元数据
        
        指定JSON序列化的额外配置。
        """
        ordered = True


class CreateConversationSchema(Schema):
    """创建对话模式
    
    用于验证创建新对话时的请求数据。
    """
    title = fields.Str(validate=validate.Length(min=1, max=100), missing='新对话')  # 对话标题
    model = fields.Str(allow_none=True)  # 使用的模型名称
    mode = fields.Str(validate=validate.OneOf(['chat', 'task_runner']), missing='chat')  # 对话模式
    
    @validates('title')
    def validate_title(self, value):
        """验证对话标题"""
        if value and len(value.strip()) == 0:
            raise ValidationError('对话标题不能为空')


class UpdateConversationSchema(Schema):
    """更新对话模式
    
    用于验证更新对话时的请求数据。
    """
    title = fields.Str(validate=validate.Length(min=1, max=100), allow_none=True)  # 对话标题
    status = fields.Str(validate=validate.OneOf(['进行中', '已完成', '失败']), allow_none=True)  # 对话状态
    model = fields.Str(allow_none=True)  # 模型名称


class SendMessageSchema(Schema):
    """发送消息模式
    
    用于验证发送消息时的请求数据。
    """
    content = fields.Str(required=True, validate=validate.Length(min=1, max=8000))  # 消息内容
    use_agent = fields.Bool(missing=True)  # 是否使用Agent模式，默认为True
    model = fields.Str(allow_none=True)  # 覆盖对话设置的模型
    stream = fields.Bool(missing=False)  # 是否使用流式返回
    
    @validates('content')
    def validate_content(self, value):
        """验证消息内容"""
        if not value or not value.strip():
            raise ValidationError('消息内容不能为空')


class MessageListResponseSchema(Schema):
    """消息列表响应模式
    
    用于验证获取消息列表时的响应数据。
    """
    messages = fields.List(fields.Nested(MessageSchema))  # 消息列表
    pagination = fields.Dict(required=True)  # 分页信息
    conversation = fields.Nested(ConversationSchema)  # 对话信息
    
    class Meta:
        """元数据
        
        指定JSON序列化的额外配置。
        """
        ordered = True


class ToolCallSummarySchema(Schema):
    """工具调用统计摘要模式
    
    用于验证Agent工具调用统计信息的序列化。
    """
    total_tool_calls = fields.Int(required=True)  # 总工具调用次数
    successful_calls = fields.Int(required=True)  # 成功调用次数
    failed_calls = fields.Int(required=True)  # 失败调用次数
    tool_names = fields.List(fields.Str(), required=True)  # 使用的工具名称列表


class ConversationSummarySchema(Schema):
    """对话摘要模式
    
    用于验证对话摘要信息的序列化，包含统计信息。
    """
    conversation = fields.Nested(ConversationSchema)  # 对话基本信息
    message_count = fields.Int(required=True)  # 消息数量
    last_message_at = fields.DateTime(allow_none=True)  # 最后消息时间
    tool_call_summary = fields.Nested(ToolCallSummarySchema, allow_none=True)  # 工具调用统计
    
    class Meta:
        """元数据
        
        指定JSON序列化的额外配置。
        """
        ordered = True